package cn.kuporo.seckill.common.lock.redisson;

import cn.kuporo.seckill.common.lock.DistributedLock;
import cn.kuporo.seckill.common.lock.factory.DistributedLockFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;


/**
 * @author: kuporo
 * @since: 2025/7/8
 * @description: 基于Redisson的分布式锁实现服务
 */
@Component
@ConditionalOnProperty(name = "distributed.lock.type",havingValue = "redisson")
@RequiredArgsConstructor
@Slf4j
public class RedissonLockFactory implements DistributedLockFactory {
    private final RedissonClient redissonClient;
    @Override
    public DistributedLock getDistributedLock(String key) {
        RLock rLock = redissonClient.getLock(key);
        return new DistributedLock() {
            @Override
            public void lock() {
                rLock.lock();
            }

            @Override
            public void lock(long leaseTime, TimeUnit unit) {
                rLock.lock(leaseTime, unit);
            }

            @Override
            public boolean tryLock() throws InterruptedException {
                return rLock.tryLock();
            }

            @Override
            public boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException {
                return rLock.tryLock(waitTime, unit);
            }

            @Override
            public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
                boolean isLockSuccess = rLock.tryLock(waitTime, leaseTime, unit);
                log.info("{}尝试获取锁[key={}], 结果: {}, 当前持有线程: {}, 剩余时间: {}ms",
                        Thread.currentThread(),
                        key,
                        isLockSuccess,
                        rLock.isHeldByCurrentThread(),
                        rLock.remainTimeToLive());
                return isLockSuccess;
            }

            @Override
            public void unlock() {
                if (isLocked() && isHeldByCurrentThread()) {
                    rLock.unlock();
                }
            }

            @Override
            public void forceUnlock() {
                rLock.forceUnlock();
            }

            @Override
            public boolean isHeldByCurrentThread() {
                return rLock.isHeldByCurrentThread();
            }

            @Override
            public boolean isLocked() {
                return rLock.isLocked();
            }

            @Override
            public long remainTimeToLive() {
                return rLock.remainTimeToLive();
            }
        };
    }
}
